﻿using Koala.Pro.Helpers;
using Serilog;
using SqlSugar;

namespace Koala.Pro.Common
{
    public class DbContext
    {
        public DbType DbType { get; private set; }

        public string ConnectionString { get; private set; }

        public SqlSugarScope Client { get; private set; }

        protected DbSetting DbSetting { get; private set; }

        public DbContext()
        {
            Init();
        }

        public DbContext(string dbConfigName)
        {
            Init(dbConfigName);
        }

        public void Init(string dbConfigName = null)
        {
            DbSetting = ConfigHelper.GetDbSettings(dbConfigName);
            DbSetting = DecryptConnectionStringIfPossible(DbSetting);
            ConnectionString = DbSetting.ConnectionString;
            if (string.IsNullOrWhiteSpace(ConnectionString))
            {
                throw new ArgumentNullException("数据库连接字符串为空");
            }
            DbType = GetSugarDbType(DbSetting);
            Client = new SqlSugarScope(new ConnectionConfig
            {
                DbType = DbType,
                ConnectionString = ConnectionString,
                InitKeyType = InitKeyType.Attribute,
                IsAutoCloseConnection = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuting = (sql, parameters) =>
                    {
                        var msg = "【SQL】\r\n" + UtilMethods.GetSqlString(DbType, sql, parameters) + "\r\n";
                        Log.Information(msg);
                    },
                    OnError = (ex) =>
                    {
                        Log.Fatal("【SQL ERROR】\r\n" + ex.Message + " \r\n");
                    }
                }
            });
        }

        private DbSetting DecryptConnectionStringIfPossible(DbSetting setting)
        {
            string text = setting.ConnectionString;
            switch (setting.DbType.ToLower())
            {
                case "mysql":
                case "oracle":
                case "npgsql":
                case "sqlserver":
                    if (text.IndexOf("data source", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("server", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        string text2 = text;
                        try
                        {
                            text2 = EncryptHelper.AES_Decrypt(text);
                        }
                        catch
                        {
                            text2 = text;
                        }
                        text = text2;
                    }
                    break;
            }
            setting.ConnectionString = text;
            return setting;
        }

        protected string GetSubValue(string connectionString, string subKeyName)
        {
            string[] array = connectionString.Split(new char[1] { ';' });
            for (int i = 0; i < array.Length; i++)
            {
                if (array[i].ToLower().IndexOf(subKeyName, StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    int num = array[i].IndexOf("=");
                    return array[i].Substring(num + 1).Trim();
                }
            }
            return string.Empty;
        }

        public SimpleClient<T> EntityDB<T>() where T : class, new()
        {
            return Client.GetSimpleClient<T>();
        }

        private DbType GetSugarDbType(DbSetting setting)
        {
            DbType result = DbType.SqlServer;
            string dbType = setting.DbType;
            if (!string.IsNullOrEmpty(dbType))
            {
                if (dbType.Equals("MySql", StringComparison.OrdinalIgnoreCase))
                {
                    result = DbType.MySql;
                }
                else if (dbType.Equals("SqlServer", StringComparison.OrdinalIgnoreCase))
                {
                    result = DbType.SqlServer;
                }
                else if (dbType.Equals("SQLite", StringComparison.OrdinalIgnoreCase))
                {
                    result = DbType.Sqlite;
                }
                else if (dbType.Equals("Oracle", StringComparison.OrdinalIgnoreCase))
                {
                    result = DbType.Oracle;
                }
                else if (dbType.Equals("Npgsql", StringComparison.OrdinalIgnoreCase))
                {
                    result = DbType.PostgreSQL;
                }
                else if (dbType.Equals("Dm", StringComparison.OrdinalIgnoreCase))
                {
                    result = DbType.Dm;
                }
            }
            return result;
        }

        public ExpressionContext GetExpressionContext()
        {
            return DbType switch
            {
                DbType.MySql => new MySqlExpressionContext(),
                DbType.SqlServer => new SqlServerExpressionContext(),
                DbType.Sqlite => new SqliteExpressionContext(),
                DbType.Oracle => new OracleExpressionContext(),
                DbType.PostgreSQL => new PostgreSQLExpressionContext(),
                DbType.Dm => new DmExpressionContext(),
                DbType.Kdbndp => new KdbndpExpressionContext(),
                _ => throw new Exception("不支持"),
            };
        }
    }

    public class DbSetting
    {
        public string DbConfigName { get; set; }

        public string DbType { get; set; } = "sqlserver";

        public string ConnectionString { get; set; }
    }
}
